package com.nd.bdc.presto.controller;

import com.nd.bdc.presto.entity.ExecuteMessage;
import com.nd.bdc.presto.entity.PrestoSelectResult;
import com.nd.bdc.presto.service.PrestoService;
import com.nd.bdc.presto.util.SpringContextUtils;
import com.nd.bdc.presto.util.ThreadManager;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


/**
 * <p>Description:  presto即席查询接口</p>
 *
 * @author ggh
 * @date 2020/6/4
 */
@Api("presto即席查询接口")
@RestController
@RequestMapping("/v1.0/sqlpad/presto")
public class PrestoController extends AbstractController{


    @Resource
    private PrestoService prestoService;

    /**
     * 数据滚动加载的入口
     *
     * @param request
     * @param response
     * @param catalog
     * @param schema
     * @param sql
     * @param startRow
     * @param fetchSize
     * @return
     * @throws Throwable
     */
    @ApiOperation("滚动加载查询数据")
    @RequestMapping(value = "/select", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    @ResponseBody
    public PrestoSelectResult select(HttpServletRequest request, HttpServletResponse response,
                                     @ApiParam("catalog") @RequestParam(value = "catalog", required = false) String catalog,
                                     @ApiParam("schema") @RequestParam(value = "schema", required = false) String schema,
                                     @ApiParam("执行的sql语句") @RequestParam("sql") String sql,
                                     @ApiParam("开始行数") @RequestParam(value = "startRow", required = false) Integer startRow,
                                     @ApiParam("加载行数") @RequestParam(value = "fetchSize", required = false) Integer fetchSize) throws Throwable{

        PrestoSelectResult result = prestoService.query(catalog,schema,sql,startRow,fetchSize);

        return result;
    }


    /**
     * 执行sql查询的入口
     * 此接口不直接返回查询结果，结果通过websocket返回到前端
     *
     * @param request
     * @param response
     * @param catalog
     * @param schema
     * @param sql
     * @param resultsetFetchSize
     * @return
     */
    @ApiOperation("执行SQL的接口，此接口不直接返回数据，只是触发sql提交，具体数据的返回解析查看：https://shimo.im/docs/GjpHpv9KR9cwGcGG/")
    @RequestMapping(value = "/execute", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<ExecuteMessage> executeSql(HttpServletRequest request, HttpServletResponse response,
                                                     @ApiParam("catalog") @RequestParam(value = "catalog", required = false) String catalog,
                                                     @ApiParam("schema") @RequestParam(value = "schema", required = false) String schema,
                                                     @ApiParam("执行的sql语句") @RequestParam(value = "sql", required = false) final String sql,
                                                     @RequestParam(value = "resultsetFetchSize", required = false) Integer resultsetFetchSize) throws Throwable{

        String channel = SpringContextUtils.getSession().getId();
        ThreadManager.getThreadPollProxy().execute(() -> {
            prestoService.execute(channel,catalog,schema,sql,resultsetFetchSize);
        });
        return buildExecuteMessageResponseEntity("触发sql提交以及获取websocket连接的channel！",channel);
    }

    /**
     * 返回presto的catalogs
     * @return
     */
    @ApiOperation("查询catalogs列表")
    @RequestMapping(value = "/catalogs", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    public Object catalogs() {

        List<String> catalogs;
        try {
            catalogs = prestoService.catalogs();
            return catalogs;
        } catch (Throwable throwable) {
            return buildExecuteMessageThrowableResponseEntity(throwable);
        }
    }

    /**
     * 返回指定 catalog 下的所有schemas
     * @param catalog
     * @return
     */
    @ApiOperation("获取指定catalog下的schemas")
    @RequestMapping(value = "/schemas", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    public Object schemas(@ApiParam("选定的catalog") @RequestParam(value = "catalog", required = true) String catalog){
        List<String> schemas;
        try {
            schemas = prestoService.schemas(catalog);
            return schemas;
        } catch (Throwable throwable) {
            return buildExecuteMessageThrowableResponseEntity(throwable);
        }
    }

    /**
     * 返回指定catalog，schema下的tables
     * @param catalog
     * @param schema
     * @return
     */
    @ApiOperation("获取指定catalog，schema下的tables")
    @RequestMapping(value = "/tables", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    public Object tables(@ApiParam("选定的catalog") @RequestParam(value = "catalog", required = true) String catalog,
                         @ApiParam("选定的schema") @RequestParam(value = "schema", required = true) String schema){
        List<String> tables;
        try {
            tables = prestoService.tables(catalog,schema);
            return tables;
        } catch (Throwable throwable) {
            return buildExecuteMessageThrowableResponseEntity(throwable);
        }
    }

    /**
     * 返回指定catalog，schema,table下的columns
     * @param catalog
     * @param schema
     * @param table
     * @return
     */
    @ApiOperation("获取指定catalog，schema，table下的columns")
    @RequestMapping(value = "/columns", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    public Object columns(@ApiParam("选定的catalog") @RequestParam(value = "catalog", required = true) String catalog,
                         @ApiParam("选定的schema") @RequestParam(value = "schema", required = true) String schema,
                          @ApiParam("选定的table") @RequestParam(value = "table", required = true) String table){
        List<String> columns;
        try {
            columns = prestoService.columns(catalog,schema,table);
            return columns;
        } catch (Throwable throwable) {
            return buildExecuteMessageThrowableResponseEntity(throwable);
        }
    }

    @ApiOperation("根据queryId来kill指定查询任务")
    @RequestMapping(value = "/kill", produces = CONTENT_TYPE_JSON, method = RequestMethod.GET)
    public Object kill(@ApiParam("选定的table") @RequestParam(value = "queryId", required = true) String queryId) throws Throwable{
        return prestoService.kill(queryId);
    }

}
